#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import requests
import json
import py2curl
from datetime import *
import time as timeS
import smtplib
from email.mime.text import MIMEText

####################################################################################################
# 全局配置
url = "http://esrest.sinaops.intra.weibo.cn/maiops/getAggData.do"
headers = {
    "Content-Type": "application/json"
}
# 手机类型
agent_os_type = {
    "iphone": "iphone",
    "android": "android"
}
#  缓存查询条件
cache_query_string = {
    "0~1G": "size_total_weibo:>=0 AND size_total_weibo:<1000000000",
    "1G~1.1G": "size_total_weibo:>=1000000000 AND size_total_weibo:<1100000000",
    "1.1G~1.2G": "size_total_weibo:>=1100000000 AND size_total_weibo:<1200000000",
    "1.2G~1.3G": "size_total_weibo:>=1200000000 AND size_total_weibo:<1300000000",
    "1.3~1.4G": "size_total_weibo:>=1300000000 AND size_total_weibo:<1400000000",
    "1.4~1.5G": "size_total_weibo:>=1400000000 AND size_total_weibo:<1500000000",
    "1.5~2G": "size_total_weibo:>=1500000000 AND size_total_weibo:<2000000000",
    "2G~∞": "size_total_weibo:>=2000000000",
}
# 数据模版
cache_template = {
    "indexName": "logstash-webview-*",
    "timeFormat": "day",
    "timestamp": "",  # 2023-01-15-00-00~2023-01-16-00-00
    "fields": {
        "subtype": "cache_size_rank",
        "agent_os_type": "",  # android 和iphone
        "query_string": "size_total_weibo:>=1000000000"  # 请查看缓存查询条件 占位
    },
}


####################################################################################################

def get_weibo_cache_data(timestamp):
    print("请求微博缓存数据<<时间：%s>>" % timestamp)
    weibo_size_data = {}
    # 微博缓存请求
    ios = request_weibo_size_by_os(template=cache_template,
                                   query_string=cache_query_string,
                                   timestamp=timestamp,
                                   os_type="iphone",
                                   isweekly=False)
    android = request_weibo_size_by_os(template=cache_template,
                                       query_string=cache_query_string,
                                       timestamp=timestamp,
                                       os_type="android",
                                       isweekly=False)
    weibo_size_data["iphone"] = calculate_data(ios)
    weibo_size_data["android"] = calculate_data(android)
    print(weibo_size_data)
    return weibo_size_data


####################################################################################################
# 封装请求数据
def request_weibo_size_by_os(template, os_type, query_string, timestamp=None, isweekly=False):
    template['fields']['agent_os_type'] = os_type
    if timestamp is not None:
        template['timestamp'] = timestamp

    date_range = timestamp.split("~")
    date_start = date_range[0]
    date_end = date_range[1]
    date_object_start = datetime.strptime(date_start, "%Y-%m-%d-%H-%M")
    if not isweekly:
        date_str = date_object_start.strftime("%Y.%m.%d")
    else:
        date_object_end = datetime.strptime(date_end, "%Y-%m-%d-%H-%M")
        start_str = date_object_end.strftime("%Y.%m.%d")
        end_str = date_object_end.strftime("%Y.%m.%d")
        date_str = f"{start_str}~{end_str}"
    result = dict()
    result["date"] = date_str
    data_range = dict()
    for key, value in query_string.items():
        template['fields']['query_string'] = value
        data = json.dumps(template, ensure_ascii=False)
        print("缓存请求配置参数 ", data)
        try:
            response_dict = reuqest_url(request_url=url, request_header=headers, request_params=data)
            print("缓存接口返回", response_dict)
            total = read_total_count(response_dict)
            print('目标值 %s' % total)
            data_range[key] = total
        except Exception as e:
            print("请求失败:", e)
            data_range[key] = 0
    result["range"] = data_range
    return result


# 请求网络
def reuqest_url(request_url, request_header, request_params):
    count = 0
    while count < 5:
        try:
            ret = requests.post(request_url, headers=request_header, data=request_params)
            curlll = py2curl.render(ret.request)
            print(curlll)
            print(ret.text)
            reJson = ret.json()
            return reJson
        except Exception as e:
            count = count + 1
            print('错误 接口 ------> 重试次数 = %d' % count, e)
            timeS.sleep(2)
    else:
        print("请求多次尚未获取数据")
        return None


# 获取命中的日志数量
def read_total_count(response_dict):
    if response_dict is None or response_dict['hits'] is None or len(response_dict['hits']) == 0 or \
            response_dict['hits']['total'] is None:
        return 0
    return response_dict['hits']['total']


# 计算前距离今天多少(days)天 是一段时间的时间区间 例如days=1是昨天0点到今天0点 days=3是大前天0点到今天0点
#  timestamp: 2021-08-19-00-00~2021-08-20-00-00
def get_lastday_range(time_format_type=1, days=1):
    now_time = datetime.now()
    if time_format_type == 1:
        lastday = (now_time + timedelta(days=-days)).strftime('%Y-%m-%d-00-00')
        today = now_time.strftime('%Y-%m-%d-00-00')
        timestamp = '%s~%s' % (lastday, today)
        return timestamp
    elif time_format_type == 2:
        lastday = (now_time + timedelta(days=-days)).strftime('%Y.%m.%d')
        return lastday


# 距离今天多少天 例如fromdays=-1是昨天 fromdays=-2是前天 是1天(当天)的时间区间(区别于get_lastday_range)
def get_thatday_range(time_format_type=1, days=1):
    now_time = datetime.now()
    that_day_time_start = now_time + timedelta(days=days)
    that_day_time_end = now_time + timedelta(days=days + 1)
    if time_format_type == 1:
        thatday_start = that_day_time_start.strftime('%Y-%m-%d-00-00')
        thatday_end = that_day_time_end.strftime('%Y-%m-%d-00-00')
        timestamp = '%s~%s' % (thatday_start, thatday_end)
        return timestamp
    elif time_format_type == 2:
        thatday_start = that_day_time_start.strftime('%Y.%m.%d')
        return thatday_start


####################################################################################################
# 计算百分比
def calculate_data(data_dict):
    range_data = dict()
    return_calculate_result = dict()
    return_calculate_result["date"] = data_dict["date"]
    if data_dict is None:
        return return_calculate_result

    exceed_1g = 0
    total_size = 0
    ranges = data_dict["range"]
    for key, value in ranges.items():
        total_size += int(value)
        if key != "0~1G":
            exceed_1g = exceed_1g + int(value)
    for key, value in ranges.items():
        range_data[key] = {"number": value, "percent": format_percentage(int(value), total_size)}
    range_data["超1g"] = {"number": exceed_1g, "percent": format_percentage(int(exceed_1g), total_size)}
    return_calculate_result["range"] = range_data
    return return_calculate_result


def format_percentage(numerator, total, percent=f'%.2f%%'):
    if total == 0.0:
        return "Data Exception"
    p = 100 * numerator / total
    if p == 0.0:
        q = '0%'
    else:
        q = percent % p
    return q


####################################################################################################

def init_html_message(weekly_content_html, month_html):
    timestamp_weekly = get_lastday_range(time_format_type=1, days=7)  # 一周
    ios_month_html = month_html["iphone"]
    android_month_html = month_html["android"]
    ios_html_table_weekly = weekly_content_html["iphone"]
    android_html_table_weekly = weekly_content_html["android"]
    content = f"""
        <html>
            <head>
              <meta charset=UTF-8>
            </head>
            <link rel=stylesheet type=text/css href="http://weiboota.sinaapp.com/css/mail.css">
            <body>
                <h2>近一周数据 -{timestamp_weekly}</h2>
                {ios_html_table_weekly}
                {android_html_table_weekly}
                <hr>
                <br>
                <h1>缓存占比列表数据<h1>
                <h2>iphone数据</h2>
                {ios_month_html}
                <h2>Android数据</h2>
                {android_month_html}
                <hr>
                <p>有问题请联系xiaodong32@</p>
            </body>
        </html>
    """
    return content


# 日常各区间占比html-返回表结构
# data: "iphone"和"android"为key value为各区间的值
def daily_publish_html(data):
    content = {}
    for os_type, data_range in data.items():
        table_html = '<table style="border-collapse: collapse;">'  # 添加样式来设置边框合并
        range = data_range["range"]
        if data_range is not None and range is not None:
            # 标题-第一行
            table_title = '<tr><th align="center" rowspan="2">类型</th>'
            for key in range:
                table_title += f'<th align="center" colspan="2">{key}</th>'
            table_title += "</tr>"
            # 标题-第二行
            table_title += "<tr>"
            for key in range:
                table_title += "<td>数量</td><td>占比</td>"
            table_title += "</tr>"
            # 整合标题
            table_html += table_title

            # 数据内容
            table_html += f'<tr><td style="border: 1px solid black; padding: 10px;">{os_type}</td>'
            for key, value in range.items():
                table_html += f'<td style="border: 1px solid black; padding: 8px;">{value["number"]}</th>'
                table_html += f'<td style="border: 1px solid black; padding: 8px;">{value["percent"]}</th>'
            table_html += '</tr>'
            table_html += '<br>'
        table_html += "</table>"
        table_html += '<br>'
        content[os_type] = table_html
    return content


def month_html_from_localfile_with_os(os_type):
    # 获取路径下的文件
    file_list = []
    if "iphone" in os_type:
        if os.path.exists(DAILY_RESULT_DIR) is False:
            print("iOS 获取数据异常")
        else:
            file_list = os.listdir(DAILY_RESULT_DIR)
    elif "android" in os_type:
        if os.path.exists(DAILY_RESULT_DIR) is False:
            print("iOS 获取数据异常")
        else:
            file_list = os.listdir(DAILY_RESULT_DIR)
    # 从路径中读出文件
    print(f"从路径中读出文件:{file_list}")
    iphone_datas = list()
    android_datas = list()
    for file_name in file_list:
        if ".DS_Store" in file_name:
            continue
        file_path = os.path.join(DAILY_RESULT_DIR, file_name)
        if os.path.exists(file_path):
            with open(file_path, 'r') as file:
                # 读取JSON文件内容
                json_data = json.load(file)
                iphone_data = json_data["iphone"]
                if iphone_data:
                    iphone_datas.append(iphone_data)
                android_data = json_data["android"]
                if android_data:
                    android_datas.append(android_data)
    # 拼凑html
    print("拼凑html")
    ios_html = month_table_with_files(iphone_datas)
    android_html = month_table_with_files(android_datas)
    return {"iphone": ios_html, "android": android_html}


# 从日志目录里获取所有的文件 datas 是所有的文件数据数组
def month_table_with_files(local_files):
    local_files.reverse()
    is_first = True
    table_html = '<table style="border-collapse: collapse;">'  # 添加样式来设置边框合并
    for afile in local_files:
        data_date = afile["date"]
        data_range = afile["range"]
        if not data_range or not isinstance(afile, dict):
            table_html += "<p>数据异常</p>"
        else:
            if is_first:
                # 标题-第一行
                table_title = '<tr><th align="center" rowspan="2">日期</th>'
                for key in data_range:
                    table_title += f'<th align="center" colspan="2">{key}</th>'
                table_title += "</tr>"
                # 标题-第二行
                table_title += "<tr>"
                for key in data_range:
                    table_title += "<td>数量</td><td >占比</td>"
                table_title += "</tr>"
                # 整合标题
                table_html += table_title
                is_first = False

            # 数据内容
            table_html += '<tr>'
            table_html += f'<td style="border: 1px solid black; padding: 10px;">{data_date}</td>'
            for key, value in data_range.items():
                table_html += f'<td style="border: 1px solid black; padding: 8px;">{value["number"]}</th>'
                table_html += f'<td style="border: 1px solid black; padding: 8px;">{value["percent"]}</th>'
            table_html += '</tr>'
            table_html += '<br>'
    table_html += "</table>"
    table_html += '<br>'
    return table_html


def send_mail(content):
    # account = str(os.environ.get('account'))
    # password = str(os.environ.get('password'))
    account = "xiaodong32@staff.sina.com.cn"
    password = "Woai710104!"
    print("构建参数account:", account)
    print("构建参数password:", password)
    # receivers = str(os.environ.get('receivers'))
    receivers = "xiaodong32@staff.sina.com.cn,"
    # receivers = "xiaodong32@staff.sina.com.cn,panhao@staff.sina.com.cn,liangliang22@staff.sina.com.cn,hailong9@staff.sina.com.cn"
    to_addrs = receivers.split(",")
    print("构建参数to_addrs:", to_addrs)
    message = MIMEText(content, "html", 'utf-8')
    message['From'] = account
    message['To'] = receivers
    message['Subject'] = '微博缓存占用-日常监控数据'
    smtpObj = smtplib.SMTP('mail.staff.sina.com.cn')
    smtpObj.login(account, password)
    smtpObj.sendmail(account, to_addrs, message.as_string())
    print("邮件发送成功")


def save_dict_to_path(filepath, cache_data):
    if os.path.exists(filepath):
        os.remove(filepath)

    with open(filepath, 'w') as file:
        # 将字典转换为 JSON 字符串并写入文件
        json.dump(cache_data, file)


####################################################################################################

DAILY_RESULT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "daily")
WEEKLY_RESULT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "weekly")


# DAILY_RESULT_DIR = os.path.join(os.environ['WORKSPACE'], "daily")
# WEEKLY_RESULT_DIR = os.path.join(os.environ['WORKSPACE'], "weekly")

def main_debug():
    that = -5
    print("=================预处理====================")
    os.makedirs(DAILY_RESULT_DIR, exist_ok=True)
    os.makedirs(WEEKLY_RESULT_DIR, exist_ok=True)
    print(f"创建目录:{DAILY_RESULT_DIR}")
    print(f"创建目录:{WEEKLY_RESULT_DIR}")
    print("=================微博缓存数据====================")
    weibo__daily_cache_data = get_weibo_cache_data(get_thatday_range(time_format_type=1, days=that))
    print("=================写文件====================")
    lastday = get_thatday_range(time_format_type=2, days=that)
    daily_file_path = os.path.join(DAILY_RESULT_DIR, f"{lastday}.json")
    save_dict_to_path(daily_file_path, weibo__daily_cache_data)


def main_release():
    print("=================预处理====================")
    os.makedirs(DAILY_RESULT_DIR, exist_ok=True)
    os.makedirs(WEEKLY_RESULT_DIR, exist_ok=True)
    print(f"创建目录:{DAILY_RESULT_DIR}")
    print(f"创建目录:{WEEKLY_RESULT_DIR}")
    print("=================微博缓存数据====================")
    weibo__daily_cache_data = get_weibo_cache_data(
        timestamp=get_lastday_range(time_format_type=1, days=1))  # 字典:"ihone"和"android"数据
    weibo_cache_data_weekly = get_weibo_cache_data(
        timestamp=get_lastday_range(time_format_type=1, days=7))  # 字典:"ihone"和"android"数据
    print("=================写文件====================")
    lastday = get_lastday_range(time_format_type=2, days=1)
    daily_file_path = os.path.join(DAILY_RESULT_DIR, f"{lastday}.json")
    save_dict_to_path(daily_file_path, weibo__daily_cache_data)
    print("=================创建邮件内容====================")
    weekly_content_html = daily_publish_html(weibo_cache_data_weekly)
    month_html = month_html_from_localfile_with_os("iphone")
    print("=================发邮件====================")
    message = init_html_message(weekly_content_html, month_html)
    send_mail(content=message)


if __name__ == '__main__':
    # main_debug()
    main_release()